#include "dht11.h"
#include "stm32f1xx_hal_cortex.h" // 新增NVIC操作头文件
#include "bsp_tim.h"
void delay_uss(uint32_t us)
{
    uint32_t delay = (HAL_RCC_GetHCLKFreq() / 4000000 * us);
    while (delay--)
    {
        ;
    }
}

/**
 * @brief  DATA引脚(PA7)设置为输出模式
 * @param  无
 * @retval 无
 */
void DHT11_IO_OUT()
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    GPIO_InitStruct.Pin = DHT11_GPIO_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(DHT11_GPIO_PORT, &GPIO_InitStruct);
}
/**
 * @brief  DATA引脚设置为输入模式
 * @param  无
 * @retval	无
 */
void DHT11_IO_IN()
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    GPIO_InitStruct.Pin = DHT11_GPIO_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(DHT11_GPIO_PORT, &GPIO_InitStruct);
}

// 复位DHT11
void DHT11_Rst(void)
{
    DHT11_IO_OUT(); // SET OUTPUT
    DHT11_LOW;      // 拉低DQ
    Delay_ms(20);  // 拉低至少18ms
    DHT11_HIGH;     // DQ=1
    Delay_us(30);   // 主机拉高20~40us
}
// 等待DHT11的回应
// 返回1:未检测到DHT11的存在
// 返回0:存在
u8 DHT11_Check(void)
{
    u8 retry = 0;
    DHT11_IO_IN();                     // SET INPUT
    while (DHT11_DQ_IN && retry < 100) // DHT11会拉低40~80us
    {
        retry++;
        Delay_us(1);
    };
    if (retry >= 100)
        return 1;
    else
        retry = 0;
    while (!DHT11_DQ_IN && retry < 100) // DHT11拉低后会再次拉高40~80us
    {
        retry++;
        Delay_us(1);
    };
    if (retry >= 100)
        return 1;
    return 0;
}
// 从DHT11读取一个位
// 返回值：1/0
u8 DHT11_Read_Bit(void)
{
    u8 retry = 0;
    while (DHT11_DQ_IN && retry < 100) // 等待变为低电平
    {
        retry++;
        Delay_us(1);
    }
    retry = 0;
    while (!DHT11_DQ_IN && retry < 100) // 等待变高电平
    {
        retry++;
        Delay_us(1);
    }
    Delay_us(40); // 等待40us
    if (DHT11_DQ_IN)
        return 1;
    else
        return 0;
}
// 从DHT11读取一个字节
// 返回值：读到的数据
u8 DHT11_Read_Byte(void)
{
    u8 i, dat;
    dat = 0;
    for (i = 0; i < 8; i++)
    {
        dat <<= 1;
        dat |= DHT11_Read_Bit();
    }
    return dat;
}
// 从DHT11读取一次数据
// temp:温度值(范围:0~50°)
// humi:湿度值(范围:20%~90%)
// 返回值：0,正常;1,读取失败
u8 DHT11_Read_Data(u8 *temp, u8 *humi)
{
    u8 buf[5];
    u8 i;
    DHT11_Rst();
    if (DHT11_Check() == 0)
    {
        for (i = 0; i < 5; i++) // 读取40位数据
        {
            buf[i] = DHT11_Read_Byte();
        }
        if ((buf[0] + buf[1] + buf[2] + buf[3]) == buf[4])
        {
            *humi = buf[0];
            *temp = buf[2];
        }
    }
    else
    {
        return 1;
    }
    return 0;
}
void DHT11_Strat(void)
{
    DHT11_IO_OUT();   //PA7设置为输出模式
	DHT11_LOW;     //主机拉低总线
	Delay_us(20); //延迟必须大于18ms ； 
	DHT11_HIGH;    //主机拉高总线等待DHT11响应
	Delay_us(30);
}
// 初始化DHT11的IO口 DQ 同时检测DHT11的存在
// 返回1 : 不存在
// 返回0 : 存在
//  u8 DHT11_Init(void)
//{
//	RCC->APB2ENR|=1<<8;    //使能PORTG口时钟
//	GPIOG->CRH&=0XFFFF0FFF;//PORTG.11 推挽输出
//	GPIOG->CRH|=0X00003000;
//	GPIOG->ODR|=1<<11;      //输出1
//	DHT11_Rst();
//	return DHT11_Check();
//  }
